package com.nameli.admin.config.shiro.auth;

import cn.hutool.core.util.IdUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.nameli.SIM.bean.entity.sys.SysToken;
import com.nameli.SIM.util.PropertiesUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author NAME-L
 * @Description token生成器(使用JWT生成)
 * 疑问：使用jwt还需要使用redis么？
 *      如果要用为何不使用redis + token(自定义) 来直接实现
 *      使用jwt + redis 的话，将jwt转换为字符串存在token中，又多了查询redis的操作
 *      又回到了原本自定义token的时候
 * @className TokenGenerator
 * @date 2021-12-31 17:37:14
 */
@Component
public class TokenGenerator {

    private static final long EXPIRE_TIME = 1 * 60 * 1000;

    public static String tokenGenerator(Long userId) {
        return generateToken(IdUtil.simpleUUID() ,userId);
    }

    private static final String JWT_KEY = PropertiesUtil.getProperty("parameter" , "JWT_KEY");

    public static String generateToken(String params , Long userId){
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        //秘钥及加密算法
        Algorithm algorithm = Algorithm.HMAC256(JWT_KEY);
        Map<String,Object> header = new HashMap<>();
        header.put("typ","JWT");
        header.put("alg","HS256");
        String token = JWT.create()
                .withHeader(header)
                .withIssuer("NAME-L")
                .withExpiresAt(date)
                .withClaim("userId" , userId)
                .withClaim("UUID", params)
                .sign(algorithm);
        return token;
    }

    /**
     * token校验
     * @param token
     * @return
     */
    public static boolean verify(String token){
        /**
         * @desc   验证token，通过返回true
         * @params [token]需要校验的串
         **/
        try {
            Algorithm algorithm = Algorithm.HMAC256(JWT_KEY);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }
    }

    public static String getValue(String token, String key) {
        if (verify(token)) {
            DecodedJWT jwt = JWT.decode(token);
            Map<String, Claim> map = jwt.getClaims();
            Claim keySet = map.get(key);
            return keySet.asString();
        } else {
            return null;
        }
    }
    public static Long getUserId(String token){
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Claim> map = jwt.getClaims();
        Claim keySet = map.get("userId");
        return keySet.asLong();
    }

}
